home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 45
/
Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso
/
Aminet
/
gfx
/
x11
/
x3270_3_2_16.lha
/
amiga_src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-06-30
|
17KB
|
644 lines
/*
* Modifications Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
* Original X11 Port Copyright 1990 by Jeff Sparkes.
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose and without fee is hereby granted,
* provided that the above copyright notice appear in all copies and that
* both that copyright notice and this permission notice appear in
* supporting documentation.
*
* Copyright 1989 by Georgia Tech Research Corporation, Atlanta, GA 30332.
* All Rights Reserved. GTRC hereby grants public use of this software.
* Derivative works based on this software must incorporate this copyright
* notice.
*/
/*
* main.c
* A 3270 Terminal Emulator for X11
* Main proceudre.
*/
#include "globals.h"
#ifndef AMIGA
#include <sys/wait.h>
#endif
#include <X11/StringDefs.h>
#include <X11/Core.h>
#include <X11/Shell.h>
#include <X11/Xatom.h>
#include <signal.h>
#include "appres.h"
#include "3270ds.h"
#include "resources.h"
#include "actionsc.h"
#include "ansic.h"
#include "charsetc.h"
#include "ctlrc.h"
#include "ftc.h"
#include "hostc.h"
#include "keymapc.h"
#include "kybdc.h"
#include "macrosc.h"
#include "menubarc.h"
#include "popupsc.h"
#include "resourcesc.h"
#include "savec.h"
#include "screenc.h"
#include "selectc.h"
#include "statusc.h"
#include "telnetc.h"
#include "togglesc.h"
#include "trace_dsc.h"
#include "utilc.h"
/* Externals */
#if defined(USE_APP_DEFAULTS) /*[*/
extern const char *app_defaults_version;
#ifdef AMIGA
const char *app_defaults_version="3.2.14";
#endif
#else /*][*/
extern String color_fallbacks[];
extern String mono_fallbacks[];
#endif /*]*/
/* Globals */
char *programname;
Display *display;
int default_screen;
Window root_window;
int screen_depth;
Widget toplevel;
XtAppContext appcontext;
Atom a_delete_me, a_save_yourself, a_3270, a_registry, a_iso8859,
a_ISO8859, a_encoding, a_1, a_state;
char full_model_name[13] = "IBM-";
char *model_name = &full_model_name[4];
Pixmap gray;
XrmDatabase rdb;
AppRes appres;
int children = 0;
Boolean exiting = False;
/* Statics */
static void peek_at_xevent(XEvent *);
static XtErrorMsgHandler old_emh;
static void trap_colormaps(String, String, String, String, String *,
Cardinal *);
static Boolean colormap_failure = False;
#if defined(LOCAL_PROCESS) /*[*/
static void parse_local_process(int *argcp, char **argv, char **cmds);
#endif /*]*/
static void parse_set_clear(int *, char **);
static void label_init(void);
static char *user_title = CN;
static char *user_icon_name = CN;
XrmOptionDescRec options[]= {
{ OptActiveIcon,DotActiveIcon, XrmoptionNoArg, ResTrue },
{ OptAplMode, DotAplMode, XrmoptionNoArg, ResTrue },
{ OptCharClass, DotCharClass, XrmoptionSepArg, NULL },
{ OptCharset, DotCharset, XrmoptionSepArg, NULL },
{ OptClear, ".xxx", XrmoptionSkipArg, NULL },
{ OptColorScheme,DotColorScheme,XrmoptionSepArg, NULL },
{ OptDsTrace, DotDsTrace, XrmoptionNoArg, ResTrue },
{ OptEmulatorFont,DotEmulatorFont,XrmoptionSepArg, NULL },
{ OptExtended, DotExtended, XrmoptionNoArg, ResTrue },
{ OptIconName, ".iconName", XrmoptionSepArg, NULL },
{ OptIconX, ".iconX", XrmoptionSepArg, NULL },
{ OptIconY, ".iconY", XrmoptionSepArg, NULL },
{ OptKeymap, DotKeymap, XrmoptionSepArg, NULL },
{ OptKeypadOn, DotKeypadOn, XrmoptionNoArg, ResTrue },
{ OptM3279, DotM3279, XrmoptionNoArg, ResTrue },
{ OptModel, DotModel, XrmoptionSepArg, NULL },
{ OptMono, DotMono, XrmoptionNoArg, ResTrue },
{ OptNoScrollBar,DotScrollBar, XrmoptionNoArg, ResFalse },
{ OptOnce, DotOnce, XrmoptionNoArg, ResTrue },
{ OptOversize, DotOversize, XrmoptionSepArg, NULL },
{ OptPort, DotPort, XrmoptionSepArg, NULL },
{ OptReconnect, DotReconnect, XrmoptionNoArg, ResTrue },
{ OptSaveLines, DotSaveLines, XrmoptionSepArg, NULL },
{ OptScripted, DotScripted, XrmoptionNoArg, ResTrue },
{ OptScrollBar, DotScrollBar, XrmoptionNoArg, ResTrue },
{ OptSet, ".xxx", XrmoptionSkipArg, NULL },
{ OptTermName, DotTermName, XrmoptionSepArg, NULL },
{ OptTraceFile, DotTraceFile, XrmoptionSepArg, NULL }
};
int num_options = XtNumber(options);
/* Fallback resources. */
#if defined(USE_APP_DEFAULTS) /*[*/
static String fallbacks[] = {
"*adVersion: fallback",
NULL
};
#else /*][*/
static String *fallbacks = color_fallbacks;
#endif /*]*/
struct toggle_name toggle_names[N_TOGGLES] = {
{ ResMonoCase, MONOCASE },
{ ResAltCursor, ALT_CURSOR },
{ ResCursorBlink, CURSOR_BLINK },
{ ResShowTiming, SHOW_TIMING },
{ ResCursorPos, CURSOR_POS },
#if defined(X3270_TRACE) /*[*/
{ ResDsTrace, DS_TRACE },
#endif /*]*/
{ ResScrollBar, SCROLL_BAR },
#if defined(X3270_ANSI) /*[*/
{ ResLineWrap, LINE_WRAP },
#endif /*]*/
{ ResBlankFill, BLANK_FILL },
#if defined(X3270_TRACE) /*[*/
{ ResScreenTrace, SCREEN_TRACE },
{ ResEventTrace, EVENT_TRACE },
#endif /*]*/
{ ResMarginedPaste, MARGINED_PASTE },
{ ResRectangleSelect, RECTANGLE_SELECT }
};
static void
usage(const char *msg)
{
if (msg != CN)
XtWarning(msg);
#if defined(X3270_MENUS) /*[*/
xs_error("Usage: %s [options] [[ps:][LUname@]hostname[:port]]", programname);
#else /*][*/
xs_error("Usage: %s [options] [ps:][LUname@]hostname[:port]", programname);
#endif /*]*/
}
static void
no_minus(char *arg)
{
if (arg[0] == '-')
usage(xs_buffer("Unknown or incomplete option: %s", arg));
}
int
main(int argc, char *argv[])
{
#if !defined(USE_APP_DEFAULTS) /*[*/
char *dname;
int i;
#endif /*]*/
Atom protocols[2];
char *cl_hostname = CN;
int ovc, ovr;
char junk;
int sl;
/* Figure out who we are */
programname = strrchr(argv[0], '/');
if (programname)
++programname;
else
programname = argv[0];
#ifdef AMIGA
if (99000>stacksize())
{
printf("This application requires at least 100000 bytes of stack!\n");
exit(1);
}
AMIGA_INIT_CME();
AMIGA_INIT_CMEBSB();
AMIGA_INIT_CMELINE();
AMIGA_INIT_CMPLXMENU();
AMIGA_INIT_HUSK();
#endif
/* Save a copy of the command-line args for merging later. */
save_args(argc, argv);
#if !defined(USE_APP_DEFAULTS) /*[*/
/*
* Figure out which fallbacks to use, based on the "-mono"
* switch on the command line, and the depth of the display.
*/
dname = CN;
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-mono"))
fallbacks = mono_fallbacks;
else if (!strcmp(argv[i], "-display") && argc > i)
dname = argv[i+1];
}
display = XOpenDisplay(dname);
if (display == (Display *)NULL)
XtError("Can't open display");
if (DefaultDepthOfScreen(XDefaultScreenOfDisplay(display)) == 1)
fallbacks = mono_fallbacks;
XCloseDisplay(display);
#endif /*]*/
/* Initialize. */
toplevel = XtVaAppInitialize(
&appcontext,
#if defined(USE_APP_DEFAULTS) /*[*/
"X3270",
#else /*][*/
"X3270xad", /* explicitly _not_ X3270 */
#endif /*]*/
options, num_options,
&argc, argv,
fallbacks,
XtNinput, True,
XtNallowShellResize, False,
NULL);
display = XtDisplay(toplevel);
rdb = XtDatabase(display);
/* Merge in the profile. */
merge_profile(&rdb);
old_emh = XtAppSetWarningMsgHandler(appcontext,
(XtErrorMsgHandler)trap_colormaps);
XtGetApplicationResources(toplevel, (XtPointer)&appres, resources,
num_resources, 0, 0);
(void) XtAppSetWarningMsgHandler(appcontext, old_emh);
#if defined(USE_APP_DEFAULTS) /*[*/
/* Check the app-defaults version. */
if (!appres.ad_version)
XtError("Outdated app-defaults file");
else if (!strcmp(appres.ad_version, "fallback"))
XtError("No app-defaults file");
else if (strcmp(appres.ad_version, app_defaults_version))
xs_error("app-defaults version mismatch: want %s, got %s",
app_defaults_version, appres.ad_version);
#endif /*]*/
#if defined(LOCAL_PROCESS) /*[*/
/* Pick out the -e option. */
parse_local_process(&argc, argv, &cl_hostname);
#endif /*]*/
/* Pick out -set and -clear toggle options. */
parse_set_clear(&argc, argv);
/* Verify command-line syntax. */
switch (argc) {
case 1:
#if !defined(X3270_MENUS) /*[*/
if (cl_hostname == CN)
usage(CN);
#endif /*]*/
break;
case 2:
if (cl_hostname != CN)
usage(CN);
no_minus(argv[1]);
cl_hostname = argv[1];
break;
case 3:
if (cl_hostname != CN)
usage(CN);
no_minus(argv[1]);
no_minus(argv[2]);
cl_hostname = xs_buffer("%s:%s", argv[1], argv[2]);
break;
default:
usage(CN);
break;
}
default_screen = DefaultScreen(display);
root_window = RootWindow(display, default_screen);
screen_depth = DefaultDepthOfScreen(XtScreen(toplevel));
/* Sort out model, color and extended data stream modes. */
appres.model = XtNewString(appres.model);
if (!strncmp(appres.model, "3278", 4)) {
appres.m3279 = False;
appres.model = appres.model + 4;
if (appres.model[0] == '-')
++appres.model;
} else if (!strncmp(appres.model, "3279", 4)) {
appres.m3279 = True;
appres.model = appres.model + 4;
if (appres.model[0] == '-')
++appres.model;
}
sl = strlen(appres.model);
if (sl && (appres.model[sl-1] == 'E' || appres.model[sl-1] == 'e')) {
appres.extended = True;
appres.model[sl-1] = '\0';
sl--;
if (sl && appres.model[sl-1] == '-')
appres.model[sl-1] = '\0';
}
if (!appres.model[0])
#if defined(RESTRICT_3279) /*[*/
appres.model = XtNewString("3");
#else /*][*/
appres.model = XtNewString("4");
#endif /*]*/
if (appres.m3279)
appres.extended = True;
if (screen_depth <= 1 || colormap_failure)
appres.mono = True;
if (appres.mono) {
appres.use_cursor_color = False;
appres.m3279 = False;
}
if (!appres.extended)
appres.oversize = CN;
if (appres.secure)
appres.disconnect_clear = True;
a_delete_me = XInternAtom(display, "WM_DELETE_WINDOW", False);
a_save_yourself = XInternAtom(display, "WM_SAVE_YOURSELF", False);
a_3270 = XInternAtom(display, "3270", False);
a_registry = XInternAtom(display, "CHARSET_REGISTRY", False);
a_ISO8859 = XInternAtom(display, "ISO8859", False);
a_iso8859 = XInternAtom(display, "iso8859", False);
a_encoding = XInternAtom(display, "CHARSET_ENCODING", False);
a_1 = XInternAtom(display, "1", False);
a_state = XInternAtom(display, "WM_STATE", False);
XtAppAddActions(appcontext, actions, actioncount);
/* Initialize fonts. */
font_init();
#if defined(RESTRICT_3279) /*[*/
if (appres.m3279 && !strcmp(appres.model, "4"))
appres.model = "3";
#endif /*]*/
if (!appres.extended || appres.oversize == CN ||
sscanf(appres.oversize, "%dx%d%c", &ovc, &ovr, &junk) != 2) {
ovc = 0;
ovr = 0;
}
set_rows_cols(atoi(appres.model), ovc, ovr);
if (appres.termname != CN)
termtype = appres.termname;
else
termtype = full_model_name;
hostfile_init();
keymap_init(appres.key_map);
if (appres.apl_mode) {
appres.compose_map = XtNewString(Apl);
appres.charset = XtNewString(Apl);
}
if (!charset_init(appres.charset))
xs_warning("Cannot find charset \"%s\"", appres.charset);
/* Initialize the icon. */
icon_init();
/*
* If no hostname is specified on the command line, ignore certain
* options.
*/
if (argc <= 1) {
#if defined(LOCAL_PROCESS) /*[*/
if (cl_hostname == CN)
#endif /*]*/
appres.once = False;
appres.reconnect = False;
}
#if !defined(X3270_MENUS) /*[*/
/*
* If there are no menus, then -once is the default; let -reconnect
* override it.
*/
if (appres.reconnect)
appres.once = False;
#endif /*]*/
if (appres.char_class != CN)
reclass(appres.char_class);
screen_init();
kybd_init();
ansi_init();
sms_init();
error_popup_init();
info_popup_init();
#if defined(X3270_FT) && !defined(X3270_MENUS) /*[*/
ft_init();
#endif /*]*/
protocols[0] = a_delete_me;
protocols[1] = a_save_yourself;
XSetWMProtocols(display, XtWindow(toplevel), protocols, 2);
/* Save the command line. */
save_init(argc, argv[1], argv[2]);
#ifndef AMIGA
/* Make sure we don't fall over any SIGPIPEs. */
(void) signal(SIGPIPE, SIG_IGN);
#endif
/* Set up the window and icon labels. */
label_init();
/* Handle initial toggle settings. */
#if defined(X3270_TRACE) /*[*/
if (!appres.debug_tracing) {
appres.toggle[DS_TRACE].value = False;
appres.toggle[EVENT_TRACE].value = False;
}
#endif /*]*/
initialize_toggles();
/* Connect to the host. */
if (cl_hostname != CN)
(void) host_connect(cl_hostname);
/* Prepare to run a peer script. */
peer_script_init();
/* Process X events forever. */
while (1) {
XEvent event;
while (XtAppPending(appcontext) & (XtIMXEvent | XtIMTimer)) {
if (XtAppPeekEvent(appcontext, &event))
peek_at_xevent(&event);
XtAppProcessEvent(appcontext,
XtIMXEvent | XtIMTimer);
}
screen_disp();
XtAppProcessEvent(appcontext, XtIMAll);
if (children
#ifndef AMIGA
&& waitpid(0, (int *)0, WNOHANG) > 0
#endif
)
--children;
}
}
/* Change the window and icon labels. */
static void
relabel(Boolean ignored unused)
{
char *title;
char icon_label[8];
if (user_title != CN && user_icon_name != CN)
return;
title = XtMalloc(10 + ((PCONNECTED || appres.reconnect) ?
strlen(reconnect_host) : 0));
if (PCONNECTED || appres.reconnect) {
(void) sprintf(title, "x3270-%d%s %s", model_num,
(IN_ANSI ? "A" : ""), reconnect_host);
if (user_title == CN)
XtVaSetValues(toplevel, XtNtitle, title, NULL);
if (user_icon_name == CN)
XtVaSetValues(toplevel,
XtNiconName, reconnect_host,
NULL);
set_aicon_label(reconnect_host);
} else {
(void) sprintf(title, "x3270-%d", model_num);
(void) sprintf(icon_label, "x3270-%d", model_num);
if (user_title == CN)
XtVaSetValues(toplevel, XtNtitle, title, NULL);
if (user_icon_name == CN)
XtVaSetValues(toplevel, XtNiconName, icon_label, NULL);
set_aicon_label(icon_label);
}
XtFree(title);
}
/* Respect the user's label/icon wishes and set up the label/icon callbacks. */
static void
label_init(void)
{
user_title = get_resource(XtNtitle);
user_icon_name = get_resource(XtNiconName);
if (user_icon_name != CN)
set_aicon_label(user_icon_name);
register_schange(ST_HALF_CONNECT, relabel);
register_schange(ST_CONNECT, relabel);
register_schange(ST_3270_MODE, relabel);
register_schange(ST_REMODEL, relabel);
}
/*
* Peek at X events before Xt does, calling PA_KeymapNotify_action if we see a
* KeymapEvent. This is to get around an (apparent) server bug that causes
* Keymap events to come in with a window id of 0, so Xt never calls our
* event handler.
*
* If the bug is ever fixed, this code will be redundant but harmless.
*/
static void
peek_at_xevent(XEvent *e)
{
static Cardinal zero = 0;
if (e->type == KeymapNotify) {
ia_cause = IA_PEEK;
PA_KeymapNotify_action((Widget)NULL, e, (String *)NULL, &zero);
}
}
/*
* Warning message trap, for catching colormap failures.
*/
static void
trap_colormaps(String name, String type, String class, String defaultp,
String *params, Cardinal *num_params)
{
if (!strcmp(type, "cvtStringToPixel"))
colormap_failure = True;
(*old_emh)(name, type, class, defaultp, params, num_params);
}
#if defined(LOCAL_PROCESS) /*[*/
/*
* Pick out the -e option.
*/
static void
parse_local_process(int *argcp, char **argv, char **cmds)
{
int i, j;
int e_len = -1;
for (i = 1; i < *argcp; i++) {
if (strcmp(argv[i], OptLocalProcess))
continue;
/* Matched. Copy 'em. */
e_len = strlen(OptLocalProcess) + 1;
for (j = i+1; j < *argcp; j++) {
e_len += 1 + strlen(argv[j]);
}
e_len++;
*cmds = XtMalloc(e_len);
(void) strcpy(*cmds, OptLocalProcess);
for (j = i+1; j < *argcp; j++) {
(void) strcat(strcat(*cmds, " "), argv[j]);
}
/* Stamp out the remaining args. */
*argcp = i;
argv[i] = CN;
break;
}
}
#endif /*]*/
/*
* Pick out -set and -clear toggle options.
*/
static void
parse_set_clear(int *argcp, char **argv)
{
int i, j;
int argc_out = 0;
char **argv_out = (char **) XtMalloc((*argcp + 1) * sizeof(char *));
argv_out[argc_out++] = argv[0];
for (i = 1; i < *argcp; i++) {
Boolean is_set = False;
if (!strcmp(argv[i], OptSet))
is_set = True;
else if (strcmp(argv[i], OptClear)) {
argv_out[argc_out++] = argv[i];
continue;
}
if (i == *argcp - 1) /* missing arg */
continue;
/* Delete the argument. */
i++;
for (j = 0; j < N_TOGGLES; j++)
if (!strcmp(argv[i], toggle_names[j].name)) {
appres.toggle[toggle_names[j].index].value =
is_set;
break;
}
if (j >= N_TOGGLES)
usage("Unknown toggle name");
}
*argcp = argc_out;
argv_out[argc_out] = CN;
(void) memcpy((char *)argv, (char *)argv_out,
(argc_out + 1) * sizeof(char *));
XtFree((XtPointer)argv_out);
}